{# Layout macros: the pieces that frame a page rather than fill it. Import what you need: {% from "components/macros/layout.html" import card, stat_tile, dialog, dropdown %} #} {% from "components/macros/feedback.html" import empty_state %} {% from "components/macros/form.html" import action, cancel_button %} {% from "components/macros/icons.html" import icon %} {# Rendered markdown's typography (``|markdown``): an answer in the chat or from a meeting's agent, styled once. #} {% set prose = "text-sm leading-relaxed text-aegis-text [&_p]:my-2 [&_h1]:text-xl [&_h1]:font-semibold [&_h1]:mt-5 [&_h1]:mb-2 [&_h2]:text-lg [&_h2]:font-semibold [&_h2]:mt-5 [&_h2]:mb-2 [&_h3]:font-semibold [&_h3]:mt-4 [&_h3]:mb-1 [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-2 [&_li]:my-0.5 [&_strong]:font-semibold [&_code]:font-mono [&_code]:text-xs [&_code]:text-aegis-teal [&_pre]:rounded [&_pre]:bg-aegis-bg [&_pre]:border [&_pre]:border-aegis-border [&_pre]:p-3 [&_pre]:my-2 [&_pre]:overflow-x-auto [&_pre_code]:text-aegis-text [&_table]:my-2 [&_th]:text-left [&_th]:font-medium [&_th]:pr-4 [&_td]:pr-4 [&_td]:py-0.5 [&_a]:text-aegis-teal [&_blockquote]:border-l-2 [&_blockquote]:border-aegis-border [&_blockquote]:pl-3 [&_blockquote]:text-aegis-muted" %} {# Navigation icons share one outline style. Unknown plugin entries use the four-square icon, so every installed item has an icon. #} {% macro sidebar_icon(name) %} {% set paths = { "overview": "M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1v-9.5Z", "patterns": "M4 4h6v6H4z M14 4h6v6h-6z M4 14h6v6H4z M17 14v6 M14 17h6", "code": "M8 7l-5 5 5 5 M16 7l5 5-5 5 M14 4l-4 16", "secrets": "M15.5 7.5a3.5 3.5 0 1 1-4.95 3.18L3 18.25V21h2.75v-1.75h1.75V17.5h1.75l1.6-1.6A3.5 3.5 0 0 1 15.5 7.5Z M16.5 10.5h.01", "settings": "M4 6h16 M4 12h16 M4 18h16 M9 4v4 M15 10v4 M7 16v4", "logs": "M4 5h16v14H4z M7 9h6 M7 12h10 M7 15h8", "deploy": "M7 18a5 5 0 1 1 .9-9.9A6 6 0 0 1 19 10a4 4 0 0 1-1 8H7z M12 11v6 M9.5 13.5 12 11l2.5 2.5", "deployments": "M12 3l4 4h-3v7h-2V7H8l4-4z M4 14v5h16v-5", "resources": "M7 7h10v10H7z M10 10h4v4h-4z M10 3v4 M14 3v4 M10 17v4 M14 17v4 M3 10h4 M3 14h4 M17 10h4 M17 14h4", "backend": "M4 4h16v7H4z M4 13h16v7H4z M8 7.5h.01 M8 16.5h.01 M12 7.5h6 M12 16.5h6", "web_frontend": "M3 4h18v16H3z M3 9h18 M6 6.5h.01 M9 6.5h.01 M12 6.5h.01", "frontend": "M3 4h18v14H3z M8 21h8 M12 18v3", "database": "M4 6c0-2 16-2 16 0v12c0 2-16 2-16 0V6z M4 6c0 2 16 2 16 0 M4 12c0 2 16 2 16 0", "worker": "M12 3v3 M12 18v3 M3 12h3 M18 12h3 M5.6 5.6l2.1 2.1 M16.3 16.3l2.1 2.1 M18.4 5.6l-2.1 2.1 M7.7 16.3l-2.1 2.1 M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z", "scheduler": "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18z M12 7v5l3 2", "cache": "M13 2 5 13h6l-1 9 9-12h-6l1-8Z", "storage": "M4 4h16v4H4z M5 8v12h14V8 M10 12h4", "ingress": "M3 7h16 M15 3l4 4-4 4 M21 17H5 M9 13l-4 4 4 4", "observability": "M3 20V4 M3 20h18 M6 15l4-4 3 2 5-6 M16 7h2v2", "browser": "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18z M3 12h18 M12 3c2.5 2.5 3.8 5.5 3.8 9s-1.3 6.5-3.8 9 M12 3c-2.5 2.5-3.8 5.5-3.8 9s1.3 6.5 3.8 9", "ollama": "M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z M12 12l8-4.5 M12 12v9 M12 12 4 7.5", "auth": "M5 10h14v11H5z M8 10V7a4 4 0 0 1 8 0v3 M12 14v3", "ai": "M12 2l2.2 6.8L21 11l-6.8 2.2L12 20l-2.2-6.8L3 11l6.8-2.2L12 2z M19 18v4 M17 20h4", "comms": "M4 4h16v12H9l-5 4V4z M7 8h10 M7 12h7", "documents": "M6 3h9l4 4v14H6z M15 3v5h4 M9 12h7 M9 16h7", "meetings": "M3 7h12v10H3z M15 10.5 21 7v10l-6-3.5", "research": "M10.5 3a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15z M16 16l5 5", "mcp": "M9 3v5 M15 3v5 M6 8h12v4a6 6 0 0 1-12 0V8z M12 18v3", "insights": "M3 20h18 M5 17v-5h3v5 M11 17V7h3v10 M17 17V4h3v13", "payment": "M3 5h18v14H3z M3 10h18 M7 15h4", "finance": "M12 3c5 0 9 2 9 4s-4 4-9 4-9-2-9-4 4-4 9-4z M3 7v5c0 2 4 4 9 4s9-2 9-4V7 M3 12v5c0 2 4 4 9 4s9-2 9-4v-5", "blog": "M5 4h11l3 3v13H5z M15 4v4h4 M8 12h8 M8 16h5", "default": "M3 3h7v7H3z M14 3h7v7h-7z M3 14h7v7H3z M14 14h7v7h-7z" } %} {% endmacro %} {# A titled surface. The body comes via {% call %}; the heading id ties the section to its title for assistive tech. ``id`` lets a page target the card with htmx; it defaults to a slug of the title. #} {% macro card(title=None, subtitle=None, id=None) %} {% set card_id = id or ("card-" ~ title|lower|replace(" ", "-")) %}
{# A card whose page title already names it (the forecast's chart) goes without a header rather than repeating the words. #} {% if title %}

{{ title }}

{% if subtitle %}

{{ subtitle }}

{% endif %}
{% endif %} {{ caller() }}
{% endmacro %} {# One headline figure. Render a row of them inside a ``
``. Red once a figure goes negative and nothing otherwise: when every healthy number is coloured, colour stops meaning anything. #} {% macro stat_tile(label, value, negative=False, caption=None, attrs="") %}
{{ label }}
{{ value }}
{% if caption %}
{{ caption }}
{% endif %}
{% endmacro %} {# A thin native progress bar; ``tone`` colours it (see badge). No ``ratio`` is work under way for as long as it takes: a band sweeps it. #} {% macro progress(ratio, tone="ok", label=None, size="h-1") %} {% endmacro %} {# A reusable current-use meter. The caller supplies the resource's detail text; health thresholds already determine the metric's status and tone. #} {% macro resource_bar(label, metric, detail="") %} {% set percent = metric.metadata.get("percent_used") if metric else none %}
{{ label }} {% if percent is number %}{{ "%.1f"|format(percent) }}% {% else %}Checking…{% endif %}
{% if percent is number %} {% set tone = metric.status.value|health_tone %} {{ progress(percent / 100, tone, label ~ " usage", "h-2") }} {% else %}{% endif %} {% if detail and percent is number %}

{{ detail }}

{% endif %}
{% endmacro %} {# A chart card (JS island #1). The canvas declares its kind and points at a JSON data block; static/js/charts.js mounts Chart.js over every ``canvas[data-chart]`` on load and after each htmx settle. Data shape: ``{"labels": [...], "series": [{"label": ..., "values": [...]}], "slices": [{"categories": [...]}], "format": ...}`` (``slices`` only for drilldowns; ``format`` as charts.js formatValue reads it). A live time chart's data is ``series.chart``'s, which documents its keys. ``drilldown`` is the URL a slice click loads into the dialog; the slice's categories are appended as ``category=`` params. #} {% macro chart_panel(id, title, kind, data, drilldown=None, subtitle=None, live=None, empty=None) %} {# ``title`` may be ``None``: the canvas keeps its aria-label either way. ``live``: the stream around it (``sse-connect``) re-sends ``chart_data(id, ...)`` as the event ``id``, and charts.js updates the drawn chart in place. ``empty`` is said over the chart while its data has no ``points`` (``series.chart`` counts them; charts.js keeps it in step). #} {% call card(title, subtitle, id="chart-" ~ id) %} {{ chart(id, kind, data, label=title, drilldown=drilldown, live=live, empty=empty) }} {% endcall %} {% endmacro %} {# The canvas charts.js draws, and the data beside it: the one recipe, for a page's panel and for a card the assistant draws in chat alike. #} {% macro chart(id, kind, data, height="h-64", label=None, drilldown=None, live=None, empty=None) %}
{% if empty %}

{{ empty }}

{% endif %}
{% if live %}
{{ chart_data(id, data) }}
{% else %}{{ chart_data(id, data) }}{% endif %} {% endmacro %} {# A chart's data, as chart_panel renders it and as a live stream sends it again. #} {% macro chart_data(id, data) -%} {%- endmacro %} {# The one modal. Native : focus trap, Escape and backdrop come free. Content is loaded by htmx into ``#dialog-body`` (pattern 4); app.js opens the dialog when a swap lands there, and closing clears it so a stale body never flashes on the next open. A chat card opened larger sits on the page's own black, as it does in the thread; a tool run (its script and output, read line by line) gets room, and so does a form with much to pick from (``data-wide``). Mounted once by the app shell, outside ``#app-content``. #} {% macro dialog() %}
{% endmacro %} {# A brand mark before a name: the icon on a light tile when there is one (served from a cached URL, not inlined, so the browser fetches it once), else the initial letter. The letter rides a data attribute, not text, so the cell's text stays just the name. The tile is light in every theme: plenty of logos are drawn dark on transparency, invisible on a dark surface. #} {# ``size``: ``xs`` a footer's tiny tile, ``sm`` a table row's, ``lg`` a group heading's. Each is (tile, mark, letter, mark px), spelled out so Tailwind sees every class. #} {% set _avatar_sizes = { "xs": ("w-3.5 h-3.5", "w-2.5 h-2.5", "text-[8px]", 10), "sm": ("w-5 h-5", "w-3.5 h-3.5", "text-xxs", 14), "lg": ("w-7 h-7", "w-5 h-5", "text-xs", 20), } %} {% macro avatar(name, icon_url=None, size="sm") %} {% set tile, mark, letter, px = _avatar_sizes[size] %} {% if icon_url %} {% else %} {% endif %} {% endmacro %} {# The one drawer: one item of a list, sliding in from the right over the page. Non-modal, so the list stays clickable and rows can be walked without closing it. A list says which item is open with ``drawer_sync`` and app.js does the rest; mounted once by the app shell, beside the modal. #} {# The side drawer. Opened non-modally (it sits beside the page), so it stacks by z-index: above the chat drawer's overlay (z-50), which a reply's agent settings open from. Wider for a drawer with a table of several columns (``data-wide``). #} {% macro drawer() %}
{% endmacro %} {# Which drawer a list has open: ``url`` loads into it, or none closes it. ``param`` is the query parameter that holds the open item, dropped from the address when the drawer is closed. #} {% macro drawer_sync(url, param) %}{% endmacro %} {# What every layout's needs to wear a theme: the theme script, told which themes exist and which this page opens with (fixed, when the layout owns its theme and only the mode is the viewer's), then the theme's type and the stylesheet. The script comes first on purpose: a stored choice is applied before the stylesheet paints. #} {% macro appearance_head(theme, fixed=false) %} {% if theme.type.fonts %} {% if theme.type.fonts.startswith("https://fonts.googleapis.com") %} {% endif %} {% endif %} {% endmacro %} {# Steward's theme and mode chooser, shared by navbars and auth pages. #} {# ``label`` names the menu (the viewer's email in Overseer's); ``more`` adds choices the server draws the page by (``MenuChoice``: kept in a cookie, the page reloaded), and a ``{% call %}`` adds rows under them. #} {% macro theme_toggle(placement="down", rail=False, label="Appearance", more=()) %}
{% if rail %}{{ label }}{% else %}{{ label }}{% endif %}
{% for key, legend, choices, cookie, chosen in [("theme", "Theme", theme_choices, none, none), ("mode", "Mode", [("dark", "Dark"), ("light", "Light"), ("system", "System")], none, none)] + more|list %}
{{ legend }}
{% for value, label in choices %} {% endfor %}
{% endfor %} {% if caller is defined %}{{ caller() }}{% endif %}
{% endmacro %} {# Full-bleed dismiss layer behind a modal. Pair it with the modal panel:
{{ modal_scrim("close()") }}
...
#} {% macro modal_scrim(dismiss_handler="open = false") %}
{% endmacro %} {# THE tooltip panel — the one popover shell every hover/help hint uses. Callers provide the open/show()/hide() Alpine state on a ``relative`` wrapper and pass the body via {% call %}. Its look is ``.tooltip-panel`` (input.css), which the map's CSS-only hints share. #} {% macro popover_panel(align='left') %} {% endmacro %} {# The map's hover hint: the tooltip panel, CSS-only (the caller's hover rule shows it, so a live frame cannot close it), placed by the caller's ``classes`` and ``style``; padded, not spaced, so the pointer can move into it, and a long body scrolls inside it, never the page. The body via {% call %}. #} {% macro hint_panel(extra="", classes="", style="") %} {% endmacro %} {# Inline definition hint — wrap a term via {% call %}; hovering (or tapping) opens the shared popover panel. Dotted underline signals the affordance without a "?" button. ``align='right'`` for terms near the right edge. #} {% macro hover_hint(title, text, align='left') %} {{ caller() }} {% call popover_panel(align) %}
{{ title }}
{{ text }}
{% endcall %}
{% endmacro %} {# Small ? info icon with a click-triggered popover. Body can be arbitrary HTML (caller passes it as the macro body via {% call %}). #} {% macro info_tooltip(width="w-64") %}
{{ caller() }}
{% endmacro %} {# A small status word with a dot: ``tone`` is ok, warn, error, muted or accent; no tone renders the label plain. One shape for every "state" cell and chip, so tests find them by role. #} {% macro badge(label, tone=None) %} {% if tone %}{% endif %}{{ label }} {% endmacro %} {# A health status as a dot in its tone, its word for a reader: the sidebar's, the sub-menu's, a map chip's, and a healthy badge. #} {# A chart-ramp color as a small dot (--aegis-chart-``n``, 1 to 11): how a list marks whose a row is (a service's log lines, a meeting's speaker), leaving the text itself plain. #} {# A fold's mark, in its ````: turned while the fold is open (``.fold-mark``). ``classes`` place it (``mt-0.5`` beside a heading). #} {% macro fold_mark(classes="") -%} {%- endmacro %} {% macro chart_dot(n) -%} {%- endmacro %} {% macro status_dot(status) -%} {% set tone = status|health_tone %}{{ status }} {%- endmacro %} {# A health status: healthy is only its dot (saying so is noise), anything else says what it is. #} {% macro health_badge(status) -%} {% if status == "healthy" %}{{ status_dot(status) }} {%- else %}{{ badge(status or "unknown", (status or "")|health_tone) }}{% endif %} {%- endmacro %} {# A dropdown() menu's group heading (Download, Copy; a schema), its ``glyph`` before it; a ``tag`` other than ``li`` where it heads rows inside one item (a filtered list). #} {% macro menu_heading(label, glyph=None, tag="li", attrs="") %} <{{ tag }} {{ attrs|safe }} class="flex items-center gap-1.5 px-3 pt-2 pb-1 text-xxs caps text-aegis-muted">{% if glyph %}{{ icon(glyph, "w-3 h-3") }}{% endif %}{{ label }} {%- endmacro %} {# One entry in a dropdown() menu: a button, its htmx verb in ``attrs`` (``hx-get``/``hx-post``/``hx-delete`` plus target and swap), or a link to ``url`` (``attrs`` adding ``download``, say). The menu closes on the click (app.js), so a dialog never opens under it. ``hint``: a muted line under the label, what choosing it costs. #} {% macro menu_item(label, attrs="", danger=False, hint=None, url=None) %} {%- set tag = "a" if url else "button" %}
  • <{{ tag }} {% if url %}href="{{ url }}" {{ attrs|safe }}{% else %}type="button" {{ attrs|button_attrs|safe }}{% endif %} class="block w-full text-left px-3 py-1.5 text-sm {{ 'text-error' if danger else 'text-aegis-text' }} hover:bg-aegis-border/30 rounded transition-colors">{{ label }}{% if hint %}{{ hint }}{% endif %}
  • {% endmacro %} {# A menu behind a button. It opens below on the ``align`` side; app.js (``placeDropdown``, keyed on ``data-dropdown``) opens it above when it would run off the bottom of the window, and keeps it on a phone's screen, and closes it on a click off it. ``options`` is a row's or a drawer's rarer actions behind a bare "..." (a data_table's ``actions``), out of sight until wanted. #} {% macro dropdown(label="…", align="right", options=False) %}
    {% if options %} {{ label }} {% else %} {{ label }} {% endif %}
    {% endmacro %} {# A confirmation as dialog body: what will happen, one destructive action (``method`` is the htmx verb for ``url``: delete, post, patch; ``attrs`` rides on its button; ``tone`` is the ``action`` tone, danger unless the action is not destructive), and a way out. The action's response closes the dialog and navigates or swaps as it sees fit; nothing swaps here (hx-swap="none"). #} {# A dialog's heading: what this is, and the one line under it. ``subtitle`` is a sentence - what the dialog is for, or what it will do. ``facts`` is a metadata line (kind, date, size) and is set in the label voice instead. A ``{% call %}`` block supplies that line itself when it carries markup. The margin belongs here because it depends on whether anything follows: a title with a line under it sits close to it, a title alone stands off from the form below. Written out at each dialog it drifts - downstream it had reached four different answers across thirty-five. #} {% macro dialog_title(title, subtitle=None, facts=None) %} {%- set under = subtitle or facts or caller is defined %}

    {{ title }}

    {%- if facts %}

    {{ facts }}

    {%- elif subtitle %}

    {{ subtitle }}

    {%- elif caller is defined %} {{ caller() }} {%- endif %} {% endmacro %} {% macro confirm(title, body, url, label="Remove", method="delete", attrs="", tone="danger") %} {{ dialog_title(title, body) }}
    {% set verb %}hx-{{ method }}="{{ url }}" hx-swap="none" {{ attrs|safe }}{% endset %} {{ cancel_button() }} {{ action(label, verb, tone) }}
    {% endmacro %} {# The page header, dashboard shape: title and subtitle on the left, and whatever the caller puts on the right (headline ``figures``, chips, actions) in the same row. Every section opens with one. #} {% macro page_header(title, subtitle=None) %}

    {{ title }}

    {% if subtitle %}

    {{ subtitle }}

    {% endif %}
    {{ caller() if caller is defined }}
    {% endmacro %} {# Headline figures for a header: label over a large number, right-aligned. ``items`` are ``{"label", "value", "negative"}``; ``negative`` colours the number, nothing else does. #} {% macro figures(items) %}
    {% for item in items %}
    {{ item.label }}
    {{ item.value }}
    {% endfor %}
    {% endmacro %} {# One bordered strip of N cells (the Budget's month equation). Each cell is ``{"label", "value", "caption", "tone", "attrs"}``; ``attrs`` makes it a door (hx-get) and ``tone`` (ok, warn, error) colours the value. #} {% macro stats_strip(cells, id=None, attrs="") %} {# ``lg:grid-cols-N`` is looked up, never interpolated: Tailwind emits the classes it can SEE in the markup, and a class built at render time is not one of them - ``lg:grid-cols-{{ cells|length }}`` compiled to nothing and every strip stayed two columns at every width. #}
    {% for cell in cells %}
    {# A figure that can explain itself has to LOOK like it does: the hover fill is only found by the mouse already on it. The mark is for ``explain`` alone, not for any clickable cell - a cell that filters a list is not offering to define a word. #}
    {{ cell.label }} {% if cell.explain %}{% endif %}
    {{ cell.value }}
    {% if cell.caption %}
    {{ cell.caption }}
    {% endif %}
    {% endfor %}
    {% endmacro %} {# Ranked rows: name, a small count, the amount, and a thin bar scaled to the largest row (the Overview's payees and bills, a meeting's speakers). ``rows`` are ``{"label", "count", "value", "ratio", "tone"}``, and a ``dot`` (a chart-ramp color, ``chart_dot``) marks whose a row is; ``tone`` is "accent" or "muted" (a row standing apart), else teal; ``columns`` sets a long list in columns, read down each, so it does not run the page long. #} {% macro ranked_rows(rows, columns=False) %}
      {% for row in rows %}
      {% if row.dot %}{{ chart_dot(row.dot) }}{% endif %}{{ row.label }} {% if row.count %}{{ row.count }}{% endif %}{{ row.value }}
      {% endfor %}
    {% endmacro %} {# Tabs: sibling views of one page, Pulse's underline recipe (the same look Flet's tabs had). ``tab_bar`` is the row (``role="tablist"``); each ``tab_item`` is a link: ``href`` for a cold load, ``hx`` the htmx attributes (``hx_replace(...)`` or a plain string). #} {% macro tab_bar(label, id=None, attrs="") %} {% endmacro %} {% macro tab_item(label, active=False, href="", hx="") %} {{ label }} {% endmacro %} {# Tabs within one view, switched in the browser (app.js's ``data-tabs``): ``tabs`` is each (key, label), ``open`` the key shown first (the first when none), and each panel a ``tab_panel(key, open)`` in the caller. The tab picked stays picked when the view re-reads itself, and a link to something in a hidden panel (a note's line) shows that panel first. #} {% macro tabbed(name, tabs, open=None) %} {% set open = open or tabs[0][0] %}
    {% call tab_bar(name) %} {% for key, label in tabs %} {% endfor %} {% endcall %} {{ caller() }}
    {% endmacro %} {% macro tab_panel(key, open) %}
    {{ caller() }}
    {% endmacro %} {# A chip: one of a row of exclusive choices (a time window, a month, a view). Pulse's date-range recipe, which the Flet range chips copied: small, outlined, a light teal fill when chosen. #} {% macro chip(label, active=False, href="", hx="", extra="") %} {{ label }} {% endmacro %} {# A line drawn small (``series.sparkline``'s points, in its box): a queue's waiting jobs, a card's CPU. ``extra`` sizes it; ``tone`` (warn, error) colours it, as a figure past its threshold. #} {% macro sparkline(points, extra="", tone="") %} {% endmacro %} {# Copy ``value`` to the clipboard and confirm with a toast. The value rides in a data attribute, so it is escaped like any other markup. #} {% macro copy_button(value, label="Copy") %} {# app.js copies it (the one copier, with the plain-http fallback). #} {% endmacro %} {# A part read when it first comes on screen (a detail row's load), from ``url`` into this element; ``attrs`` is markup that marks it. #} {% macro lazy(url, attrs="", placeholder="") %}
    {{ placeholder }}
    {% endmacro %} {# A command to run, in monospace, with its copy button. #} {% macro command(value) %}{{ value }}{{ copy_button(value) }}{% endmacro %} {# The same as an icon, for a copy that sits beside what it copies (a chat bubble, a log cell): the icon becomes a tick and pops, then settles back, since without it the button looks broken and gets pressed twice. ``extra`` carries the caller's reveal rule. #} {% macro copy_icon(value, extra="") %} {% endmacro %} {# A block of source in the code block's box: highlighted by the ``highlight`` filter for ``lang`` (``pytb`` a Python traceback) or for ``filename``, plain without either; ``lines`` numbers it. ``wrap`` wraps long lines (data such as a response body or a curl command) rather than scrolling them, so the block never widens what holds it. #} {% macro highlighted(text, lang=None, wrap=False, filename=None, lines=False) %} {% set box = "code-block" ~ (" code-block--wrap" if wrap else "") %} {% if lang or filename %}
    {{ text|highlight(lang, filename, lines) }}
    {% else %}
    {{ text }}
    {% endif %} {% endmacro %} {# ``highlighted`` (SQL, Python) with a copy button, which always takes the plain text. ``caption`` is a line above it, such as the file it came from. #} {% macro code_block(text, caption=None, lang=None, wrap=False, filename=None, lines=False) %}

    {{ caption or "" }}

    {{ copy_button(text) }}
    {{ highlighted(text, lang, wrap, filename, lines) }}
    {% endmacro %} {# Label/value rows: a component's status, an expanded row's details. ``rows`` are (label, value) pairs; empty values are skipped. #} {% macro facts(rows) %}
    {% for label, value in rows if value not in (none, "", [], {}) %}
    {{ label }}
    {{ value|docstring if value is string else value|join(", ") if value is iterable and value is not mapping else value }}
    {% endfor %}
    {% endmacro %} {# A wrapping row of label-over-value figures, the Flet detail row. ``items`` are (label, value) pairs. #} {% macro stat_row(items) %}
    {% for label, value in items %}
    {{ label }}
    {{ value }}
    {% endfor %}
    {% endmacro %}